package gamesolitaire;

import java.util.ArrayList;
import java.util.Stack;

public class Board {

private Cell activeCell;
private ArrayList<int[]> validMove; 
private int[][] level;
private int selectedRow = -1;
private int selectedCol = -1;
private Stack<Move> moves;
private Move lastMove;

	/**constructor*/
	public Board () {
		this.moves = new Stack<Move>();
	}
	
	/**method gets the value of row and column*/
	public int getCellValue(int row, int col){
		return	this.level[row] [col];
	}
	
	/** gets cellValue*/
	public int getCellValue(Cell cell){
		return this.level[cell.row][cell.col];
	}
	
    /**Sets the value for given row and column */
    private void setCellValue(int row, int col, int value) {
            this.level[row][col] = value;
    }
    
    /**Sets the value for given row and column */
    private void setCellValue(Cell cell, int value) {
            this.level[cell.row][cell.col] = value;
    }
	
	/**method get RowLength*/
	public int getRowLength () {
		return this.level.length ;
	}
	
	/**method gets ColLenght*/
	public int getColLength () {
		return this.level.length ;
	}
	
	/**method gets if Peg is selected*/
	public boolean isSelected() {
		return this.activeCell != null;
	}
	
	/**method sets Board*/
	public void setLevel (int[][] level){
		this.level = level;
	}
	
	/**method looks if a peg is selected*/
	public void select (int row , int col){
		if (this.getCellValue(row, col) == 1) {
			undoSelect();
			this.setCellValue(row, col, 2);
            this.activeCell = new Cell(row, col);
            
		}
	}
	
	/** Undo select a peg*/
	public void undoSelect (){
		if (this.isSelected()) {
            this.setCellValue(activeCell ,1);
            this.activeCell = null;
		}
	}
	
	/** checking surrounding pegs and confirms Move*/
    public void moveSelectedPieceTo(int row, int col) {
        int rOff;
        int cOff;
        Cell oriN;
        Cell desN;
        // Browse neighboring rows
        for (rOff = -1; rOff < 2; rOff++) {
                // Browse neighboring columns
                for (cOff = -1; cOff < 2; cOff++) {
                        //Either row or column should be equal to 0
                        if (rOff == 0 ^ cOff == 0) {
                                //determine surrounding pegs
                                oriN = new Cell(this.activeCell.row + rOff, this.activeCell.col + cOff);
                                // Determine surrounding pegs from next click
                                desN = new Cell(row + (rOff * -1), col + (cOff * -1));
                                //check for a same peg in first and second click
                                if (oriN.equals(desN)) {
                                        //double check if it contains a peg
                                        if (this.getCellValue(oriN) == 1) {
                                                // At this point we have determined a valid move
                                                Move move = new Move(this.activeCell, new Cell(row, col), oriN);
                                                this.actionMove(move);
                                                return;
                                        }
                                }
                        }
                	}
        	}
    }
    
    /**Performs the move action after validation */
    private void actionMove(Move move) {
            // Set neighbor to empty
    		this.setCellValue(move.from, 0);
            this.setCellValue(move.jump, 0);
            this.setCellValue(move.to, 1);
            this.activeCell = null;
            this.setCellValue(move.to, 1);
            this.activeCell = null;
            // Add move to history
            this.moves.push(move);
            this.lastMove = move;
    }
    
    /** Undo the last move */
    public void undo() {
            Move move;
            // Check if history is not empty
            if (this.moves.empty() != true) {
                    // Clear current selection
                    this.undoSelect();
                    // Last move gets deleted from history
                    move = this.moves.pop();
                    // Reset the origin cell
                    this.setCellValue(move.from, 1);
                    // Reset the neighbor
                    this.setCellValue(move.jump, 1);
                    // Reset the destination cell
                    this.setCellValue(move.to, 0);
                    
            }
    }
	
	
	/**Class to store position information */
    private class Cell {
            private int row;
            private int col;
            //Constructs a new board position
            public Cell(int row, int col) {
                    this.row = row;
                    this.col = col;
            }
            //Checks if two positions are equal
            @Override
            public boolean equals(Object o) {
                    Cell otherCell = (Cell)o;
                    return this.row == otherCell.row &&
                                    this.col == otherCell.col;
            }
    }
    
    /**Class to store move information */
    private class Move {
            private Cell from;
            private Cell to;
            private Cell jump;
            //Constructs a new board move
            public Move(Cell from, Cell to, Cell jump) {
                    this.from = from;
                    this.to = to;
                    this.jump = jump;
            }
    }
    
    
	/** Returns a string representation of the game board*/
	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		for (int row = 0;row < this.level.length;row++){
			for (int col = 0; col < this.level.length; col++){
				sb.append(this.level[row][col]);
			}
			sb.append("\n");
		}
		return sb.toString();
	}
}
